home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / DELPHI32 / COMPNENT / SAWIN95 / SAWIN95.ZIP / Lib / 32 / FreeWare / ChkList.pas < prev    next >
Pascal/Delphi Source File  |  1996-10-10  |  22KB  |  770 lines

  1. unit ChkList;
  2.  
  3. interface
  4.  
  5. uses
  6.   {$IFDEF WIN32}
  7.   Windows,
  8.   {$ELSE}
  9.   WinTypes, WinProcs, Menus,
  10.   {$ENDIF}
  11.   Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  12.   StdCtrls, Grids, DsgnIntf, TypInfo;
  13.  
  14. type
  15.   TCheckState = (csUnchecked, csChecked, csGrayed);
  16.   TCheckStyle = (csAutoDetect, csNew, csWin31);
  17.   TCheckMode = (cmCheckboxClick, cmDoubleClick, cmBoth);
  18.  
  19.   TRedrawEvent = procedure(Sender: TObject; AItem : LongInt) of object;
  20.  
  21.   TStateChangedEvent = procedure(Sender : TObject; Index : Integer; State : TCheckState) of object;
  22.   TStateChangeEvent = procedure(Sender : TObject; Index : Integer; var NewState : TCheckState) of object;
  23.  
  24.   TCheckListStrings = class(TStringList)
  25.   private
  26.     FOnCheckRows : TNotifyEvent;
  27.     FOnRedraw    : TRedrawEvent;
  28.     FSorted      : Boolean;
  29.     procedure SetState(Index: Integer; AState: TCheckState);
  30.     function  GetState(Index: Integer): TCheckState;
  31.     procedure SetSorted(Value : Boolean);
  32.   protected
  33.     procedure ReadState(Reader : TReader);
  34.     procedure WriteState(Writer : TWriter);
  35.     function  Transform(const S: string; PutIt : Boolean): string;
  36.     function  OldGet(Index: Integer): string;
  37.     procedure OldPut(Index: Integer; const S: string);
  38.     procedure QuickSort(L, R: Integer);
  39.   public
  40.     procedure DefineProperties(Filer : TFiler); override;
  41.     function Add(const S: string): Integer; override;
  42.     function AddObject(const S: string; AObject: TObject): Integer; override;
  43.     procedure Delete(Index: Integer); override;
  44.     procedure Insert(Index: Integer; const S: string); override;
  45.     function Get(Index: Integer): string; override;
  46.     procedure Put(Index: Integer; const S: string); override;
  47.     procedure Sort;
  48.     property Sorted: Boolean read FSorted write SetSorted;
  49.     property State[Index: Integer]: TCheckState read GetState write SetState;
  50.     property OnCheckRows: TNotifyEvent read FOnCheckRows write FOnCheckRows;
  51.     property OnRedraw   : TRedrawEvent read FOnRedraw write FOnRedraw;
  52.   end;
  53.  
  54.   TCheckListBox = class(TCustomGrid)
  55.   private
  56.     FOnStateChanged : TStateChangedEvent;
  57.     FOnStateChange  : TStateChangeEvent;
  58.     FCheckCtl3D     : Boolean;
  59.     FCheckStyle     : TCheckStyle;
  60.     FCheckMode      : TCheckMode;
  61.     FFocusRect      : TRect;
  62.     FItems          : TStrings;
  63.     FIntegralHeight : Boolean;
  64.     FItemHeight     : Integer;
  65.     FItemIndex      : Integer;
  66.     FMinWidth       : Integer;
  67.     FGrayCheckMark  : Boolean;
  68.     FShowFocusRect  : Boolean;
  69.     procedure SetItems(Value : TStrings);
  70.     procedure SetItemIndex(Value : Integer);
  71.     function GetCheckState(Index: Integer): TCheckState;
  72.     procedure SetCheckState(Index : Integer; Value : TCheckState);
  73.     procedure SetIntegralHeight(Value : Boolean);
  74.     procedure SetCheckCtl3D(Value : Boolean);
  75.     procedure SetCheckStyle(Value : TCheckStyle);
  76.     procedure SetGrayCheckMark(Value : Boolean);
  77.     procedure SetShowFocusRect(Value : Boolean);
  78.     procedure SetSorted(Value : Boolean);
  79.     function  GetSorted: Boolean;
  80.     { Private declarations }
  81.   protected
  82.     procedure Check(Sender : TObject);
  83.     procedure RedrawLine(Sender : TObject; AItem: LongInt);
  84.     procedure wmSize(var Msg: TWMSize); message WM_SIZE;
  85.     procedure cmFontChanged(Var Msg : TMessage); message CM_FONTCHANGED;
  86.     procedure cmEnabledChanged(Var Msg : TMessage); message CM_ENABLEDCHANGED;
  87.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  88.     procedure KeyPress(var Key: Char); override;
  89.     procedure DblClick; override;
  90.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  91.     procedure Toggle(const Index : Integer);
  92.     function  SetIndex(Index: Integer): Integer;
  93.     function  NewStyle: Boolean;
  94.     procedure CheckRows;
  95.     procedure Resize;
  96.     procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override;
  97.     procedure SetRowHeight;
  98.     { Protected declarations }
  99.   public
  100.     constructor Create(AOwner : TComponent); override;
  101.     destructor Destroy; override;
  102.     procedure Clear;
  103.     property ItemIndex: Integer read FItemIndex write SetItemIndex;
  104.     property State[Index: Integer]: TCheckState read GetCheckState write SetCheckState;
  105.     { Public declarations }
  106.   published
  107.     property Align;
  108.     property BorderStyle;
  109.     property Enabled;
  110.     property Font;
  111.     property CheckCtl3D: Boolean read FCheckCtl3D write SetCheckCtl3D default True;
  112.     property CheckMode: TCheckMode read FCheckMode write FCheckMode default cmBoth;
  113.     property CheckStyle: TCheckStyle read FCheckStyle write SetCheckStyle default csAutoDetect;
  114.     property Color;
  115.     property Ctl3D;
  116.     property DragCursor;
  117.     property DragMode;
  118.     property GrayCheckMark: Boolean read FGrayCheckMark write SetGrayCheckMark default False;
  119.     property IntegralHeight: Boolean read FIntegralHeight write SetIntegralHeight default True;
  120.     property Items: TStrings read FItems write SetItems;
  121.     property ItemHeight: Integer read FItemHeight;
  122.     property ParentColor;
  123.     property ParentCtl3D;
  124.     property ParentFont;
  125.     property ParentShowHint;
  126.     property PopupMenu;
  127.     property ShowHint;
  128.     property ShowFocusRect: Boolean read FShowFocusRect write SetShowFocusRect default True;
  129.     property Sorted: Boolean read GetSorted write SetSorted default False;
  130.     property TabOrder;
  131.     property TabStop;
  132.     property Visible;
  133.  
  134.     property OnClick;
  135.     property OnDblClick;
  136.     property OnDragDrop;
  137.     property OnDragOver;
  138.     property OnEndDrag;
  139.     property OnEnter;
  140.     property OnExit;
  141.     property OnKeyDown;
  142.     property OnKeyPress;
  143.     property OnKeyUp;
  144.     property OnMouseDown;
  145.     property OnMouseMove;
  146.     property OnMouseUp;
  147. {$IFDEF WIN32}
  148.     property OnStartDrag;
  149. {$ENDIF}
  150.     property OnStateChange: TStateChangeEvent read FOnStateChange write FOnStateChange;
  151.     property OnStateChanged: TStateChangedEvent read FOnStateChanged write FOnStateChanged;
  152.     { Published declarations }
  153.   end;
  154.  
  155. implementation
  156.  
  157. function min(const x, y : integer): integer;
  158. begin
  159.   if x<y then result := x else result := y;
  160. end;
  161.  
  162. function max(const x, y : integer): integer;
  163. begin
  164.   if x<y then result := y else result := x;
  165. end;
  166.  
  167. { TCheckListStrings }
  168.  
  169. function TCheckListStrings.GetState(Index: Integer): TCheckState;
  170. Var sItem : String;
  171. begin
  172.   sItem := OldGet(Index);
  173.   case sItem[1] of
  174.    '1' : Result := csChecked;
  175.    '2' : Result := csGrayed;
  176.   else   Result := csUnchecked;
  177.   end;
  178. end;
  179.  
  180. procedure TCheckListStrings.SetState(Index : Integer; AState : TCheckState);
  181. Var sItem : String;
  182. begin
  183.   sItem := Get(Index);
  184.   case AState of
  185.    csUnchecked : sItem := '0|' + sItem;
  186.    csChecked   : sItem := '1|' + sItem;
  187.    csGrayed    : sItem := '2|' + sItem;
  188.   end;
  189.   OldPut(Index, sItem);
  190. end;
  191.  
  192. procedure TCheckListStrings.SetSorted(Value : Boolean);
  193. begin
  194.   if FSorted<>Value then
  195.    begin
  196.      if Value then Sort;
  197.      FSorted := Value;
  198.    end;
  199. end;
  200.  
  201. procedure TCheckListStrings.QuickSort(L, R: Integer);
  202. var
  203.   I, J: Integer;
  204.   P: String;
  205. begin
  206.   I := L;
  207.   J := R;
  208.   P := Get((L + R) shr 1);
  209.   repeat
  210.     while AnsiCompareText(Get(I), P) < 0 do Inc(I);
  211.     while AnsiCompareText(Get(J), P) > 0 do Dec(J);
  212.     if I <= J then
  213.     begin
  214.       Exchange(I, J);
  215.       Inc(I);
  216.       Dec(J);
  217.     end;
  218.   until I > J;
  219.   if L < J then QuickSort(L, J);
  220.   if I < R then QuickSort(I, R);
  221. end;
  222.  
  223. procedure TCheckListStrings.Sort;
  224. begin
  225.   if not Sorted and (Count > 1) then
  226.   begin
  227.     Changing;
  228.     BeginUpdate;
  229.     QuickSort(0, Count - 1);
  230.     EndUpdate;
  231.     Changed;
  232.     If Assigned(FOnRedraw) then FOnRedraw(Self, -1);
  233.   end;
  234. end;
  235.  
  236. function TCheckListStrings.Transform(const S: string; PutIt : Boolean): string;
  237. var iPos : Integer;
  238. begin
  239.   Result := S;
  240.   iPos := Pos('|', S);
  241.   if PutIt then
  242.    begin
  243.      if iPos=0 then Result := '0|' + Result;
  244.    end
  245.   else
  246.    begin
  247.      if iPos>0 then Result := Copy(Result, iPos+1, Length(Result));
  248.    end;
  249. end;
  250.  
  251. function TCheckListStrings.Add(const S: string): Integer;
  252. begin
  253.   Result := inherited Add(Transform(S, True));
  254.   if Assigned(FOnCheckRows) then FOnCheckRows(Self);
  255. end;
  256.  
  257. function TCheckListStrings.AddObject(const S: string; AObject: TObject): Integer;
  258. begin
  259.   Result := inherited AddObject(Transform(S, True), AObject);
  260.   if Assigned(FOnCheckRows) then FOnCheckRows(Self);
  261. end;
  262.  
  263. procedure TCheckListStrings.Delete(Index: Integer);
  264. begin
  265.   inherited Delete(Index);
  266.   if Assigned(FOnCheckRows) then FOnCheckRows(Self);
  267. end;
  268.  
  269. procedure TCheckListStrings.Insert(Index: Integer; const S: string);
  270. begin
  271.   inherited Insert(Index, Transform(S, True));
  272.   if Assigned(FOnCheckRows) then FOnCheckRows(Self);
  273. end;
  274.  
  275. procedure TCheckListStrings.OldPut(Index: Integer; const S: string);
  276. begin
  277.   inherited Put(Index, S);
  278. end;
  279.  
  280. function TCheckListStrings.OldGet(Index: Integer): string;
  281. begin
  282.   Result := inherited Get(Index);
  283. end;
  284.  
  285. procedure TCheckListStrings.Put(Index: Integer; const S: string);
  286. Var sOld, sNew : string;
  287. begin
  288.   sOld := OldGet(Index);
  289.   sNew := Transform(S, False);
  290.   sNew := sOld[1] + '|' + sNew;
  291.   OldPut(Index, sNew);
  292.   If Assigned(FOnRedraw) then FOnRedraw(Self, Index);
  293. end;
  294.  
  295. function TCheckListStrings.Get(Index: Integer): string;
  296. begin
  297.   Result := OldGet(Index);
  298.   Result := Transform(Result, False);
  299. end;
  300.  
  301. procedure TCheckListStrings.ReadState(Reader : TReader);
  302. var
  303.    i  : integer;
  304.    ct : TCheckState;
  305. begin
  306.   i := 0;
  307.   Reader.ReadListBegin;
  308.   while not Reader.EndOfList do
  309.    begin
  310.      ct := TCheckState(GetEnumValue(TypeInfo(TCheckState), Reader.ReadString));
  311.      if i<Count then State[i] := ct;
  312.      inc(i);
  313.    end;
  314.   Reader.ReadListEnd;
  315. end;
  316.  
  317. procedure TCheckListStrings.WriteState(Writer : TWriter);
  318. var
  319.    i : Integer;
  320.    s : string;
  321. begin
  322.   i := 0;
  323.   Writer.WriteListBegin;
  324.   for i:=0 to Count-1 do
  325.   {$IFDEF WIN32}
  326.    Writer.WriteString(GetEnumName(TypeInfo(TCheckState), ord(State[i])));
  327.   {$ELSE}
  328.    Writer.WriteString(GetEnumName(TypeInfo(TCheckState), ord(State[i]))^);
  329.   {$ENDIF}
  330.   Writer.WriteListEnd;
  331. end;
  332.  
  333. procedure TCheckListStrings.DefineProperties(Filer : TFiler);
  334.  
  335. {$IFDEF WIN32}
  336.   function DoWrite: Boolean;
  337.   begin
  338.     if Filer.Ancestor <> nil then
  339.     begin
  340.       Result := True;
  341.       if Filer.Ancestor is TCheckListStrings then
  342.         Result := not Equals(TCheckListStrings(Filer.Ancestor))
  343.     end
  344.     else Result := Count > 0;
  345.   end;
  346. {$ELSE}
  347.   const DoWrite = True;
  348. {$ENDIF}
  349.  
  350. begin
  351.   inherited DefineProperties(Filer);
  352.   Filer.DefineProperty('State', ReadState, WriteState, DoWrite);
  353. end;
  354.  
  355. { TCheckListBox }
  356.  
  357. constructor TCheckListBox.Create(AOwner : TComponent);
  358. begin
  359.   inherited Create(AOwner);
  360.   FMinWidth := 13;
  361.   Width := 121;
  362.   Height := 97;
  363.   Color := clWindow;
  364.   ParentColor := False;
  365.   RowCount := 0;
  366.   ColCount := 1;
  367.   FixedCols := 0;
  368.   FixedRows := 0;
  369.   DefaultDrawing := False;
  370.   FItems := TCheckListStrings.Create;
  371.   with TCheckListStrings(FItems) do
  372.    begin
  373.      OnCheckRows := Check;
  374.      OnRedraw := RedrawLine;
  375.    end;
  376.   FItemIndex := -1;
  377.   FCheckCtl3D := True;
  378.   FCheckStyle := csAutoDetect;
  379.   FIntegralHeight := True;
  380.   FGrayCheckMark := False;
  381.   FCheckMode := cmBoth;
  382.   FShowFocusRect := True;
  383.   SetRowHeight;
  384.   CheckRows;
  385.   inherited Options := [goThumbTracking];
  386. end;
  387.  
  388. destructor TCheckListBox.Destroy;
  389. begin
  390.   FItems.Free;
  391.   inherited Destroy;
  392. end;
  393.  
  394. procedure TCheckListBox.Check(Sender : TObject);
  395. begin
  396.   CheckRows;
  397. end;
  398.  
  399. procedure TCheckListBox.RedrawLine(Sender : TObject; AItem: LongInt);
  400. begin
  401.   if AItem>=0 then
  402.    InvalidateCell(0, AItem)
  403.   else
  404.    Repaint;
  405. end;
  406.  
  407. function TCheckListBox.NewStyle: Boolean;
  408. begin
  409.   Result := ((CheckStyle = csAutoDetect) and NewStyleControls) or (CheckStyle = csNew);
  410. end;
  411.  
  412. function TCheckListBox.GetCheckState(Index: Integer): TCheckState;
  413. begin
  414.   Result := TCheckListStrings(Items).State[Index];
  415. end;
  416.  
  417. procedure TCheckListBox.SetCheckState(Index : Integer; Value : TCheckState);
  418. begin
  419.   TCheckListStrings(Items).State[Index] := Value;
  420.   InvalidateCell(0,Index);
  421. end;
  422.  
  423. procedure TCheckListBox.SetItems(Value : TStrings);
  424. begin
  425.   FItems.Assign(Value);
  426.   CheckRows;
  427. end;
  428.  
  429. procedure TCheckListBox.Clear;
  430. begin
  431.   FItems.Clear;
  432.   CheckRows;
  433. end;
  434.  
  435. procedure TCheckListBox.SetItemIndex(Value: Integer);
  436. begin
  437.   if Value<>FItemIndex then
  438.    begin
  439.      if FItemIndex>=0 then InvalidateCell(0, FItemIndex);
  440.      FItemIndex := Value;
  441.      if FItemIndex>=0 then InvalidateCell(0, FItemIndex);
  442.    end;
  443. end;
  444.  
  445. procedure TCheckListBox.SetShowFocusRect(Value : Boolean);
  446. begin
  447.   if FShowFocusRect<>Value then
  448.    begin
  449.      FShowFocusRect := Value;
  450.      if Focused then InvalidateCell(0, Col);
  451.    end;
  452. end;
  453.  
  454. procedure TCheckListbox.SetSorted(Value : Boolean);
  455. begin
  456.   TCheckListStrings(Items).Sorted := Value;
  457. end;
  458.  
  459. function TCheckListbox.GetSorted: Boolean;
  460. begin
  461.   Result := TCheckListStrings(Items).Sorted;
  462. end;
  463.  
  464. procedure TCheckListbox.Resize;
  465. Var iOffs, iRows : integer;
  466. begin
  467.   iOffs := 0;
  468.   iRows := max(1, Height div DefaultRowHeight);
  469.   if BorderStyle=bsSingle then
  470.    begin
  471.      inc(iOffs, 2);
  472.      if Ctl3D then inc(iOffs, 2);
  473.    end;
  474.   Height := iRows * DefaultRowHeight + iOffs;
  475. end;
  476.  
  477. procedure TCheckListBox.SetIntegralHeight(Value : Boolean);
  478. begin
  479.   if Value<>FIntegralHeight then
  480.    begin
  481.      if Value then Resize;
  482.      FIntegralHeight := Value;
  483.    end;
  484. end;
  485.  
  486. procedure TCheckListBox.SetCheckCtl3D(Value : Boolean);
  487. begin
  488.   if FCheckCtl3D<>Value then
  489.    begin
  490.      FCheckCtl3D := Value;
  491.      Repaint;
  492.    end;
  493. end;
  494.  
  495. procedure TCheckListBox.SetGrayCheckMark(Value : Boolean);
  496. begin
  497.   if FGrayCheckMark<>Value then
  498.    begin
  499.      FGrayCheckMark := Value;
  500.      Repaint;
  501.    end;
  502. end;
  503.  
  504. procedure TCheckListBox.SetCheckStyle(Value : TCheckStyle);
  505. begin
  506.   if FCheckStyle<>Value then
  507.    begin
  508.      FCheckStyle := Value;
  509.      Repaint;
  510.    end;
  511. end;
  512.  
  513. procedure TCheckListBox.CheckRows;
  514. begin
  515.   FItemIndex := -1;
  516.   if RowCount<>Items.Count then
  517.    begin
  518.      if Items.Count>0 then
  519.       RowCount := Items.Count
  520.      else
  521.       RowCount := 1;
  522.    end
  523.   else
  524.    Invalidate;
  525. end;
  526.  
  527. procedure TCheckListbox.SetRowHeight;
  528. var
  529.   ScreenDC: HDC;
  530.   FontSize: Integer;
  531. begin
  532.   ScreenDC := GetDC(0);
  533.   try
  534.     FontSize := MulDiv(Font.Size, GetDeviceCaps(ScreenDC, LOGPIXELSY), 72);
  535.     FItemHeight := max(FMinWidth, MulDiv(FontSize, 120, 100)+3);
  536.     DefaultRowHeight := FItemHeight;
  537.   finally
  538.     ReleaseDC(0, ScreenDC);
  539.   end;
  540. end;
  541.  
  542. procedure TCheckListBox.wmSize(var Msg: TWMSize);
  543. begin
  544.   inherited;
  545.   if IntegralHeight then Resize;
  546.   DefaultColWidth := ClientWidth;
  547. end;
  548.  
  549. procedure TCheckListBox.cmFontChanged(Var Msg : TMessage);
  550. begin
  551.   inherited;
  552.   SetRowHeight;
  553.   if IntegralHeight then Resize;
  554. end;
  555.  
  556. procedure TCheckListBox.cmEnabledChanged(Var Msg : TMessage);
  557. begin
  558.   inherited;
  559.   Repaint;
  560. end;
  561.  
  562. procedure TCheckListBox.Toggle(const Index : Integer);
  563. Var NewState : TCheckState;
  564. begin
  565.   if Index=-1 then Exit;
  566.   if State[Index]=csUnchecked then
  567.    NewState := csChecked
  568.   else
  569.    NewState := csUnchecked;
  570.   if Assigned(FOnStateChange) then FOnStateChange(Self, Index, NewState);
  571.   State[Index] := NewState;
  572.   if Assigned(FOnStateChanged) then FOnStateChanged(Self, Index, NewState);
  573. end;
  574.  
  575. procedure TCheckListBox.KeyPress(var Key: Char);
  576. begin
  577.   inherited KeyPress(Key);
  578.   if Key=#32 then Toggle(ItemIndex);
  579. end;
  580.  
  581. function TCheckListBox.SetIndex(Index : Integer): Integer;
  582. begin
  583.   if Items.Count>0 then Result := Index else Result := -1;
  584. end;
  585.  
  586. procedure TCheckListBox.KeyDown(var Key: Word; Shift: TShiftState);
  587. begin
  588.   inherited KeyDown(Key, Shift);
  589.   if Items.Count = 0 then Exit;
  590.   case Key of
  591.     VK_HOME:
  592.       begin
  593.         ItemIndex := SetIndex(0);
  594.         Exit;
  595.       end;
  596.     VK_END:
  597.       begin
  598.         ItemIndex := SetIndex(Items.Count-1);
  599.         Exit;
  600.       end;
  601.     VK_UP:
  602.       begin
  603.         if ItemIndex>0 then ItemIndex := ItemIndex-1;
  604.         Exit;
  605.       end;
  606.     VK_DOWN:
  607.       begin
  608.         if ItemIndex<Items.Count-1 then ItemIndex := SetIndex(ItemIndex+1);
  609.         Exit;
  610.       end;
  611.   end;
  612. end;
  613.  
  614. procedure TCheckListBox.DblClick;
  615. begin
  616.   inherited DblClick;
  617.   if (CheckMode=cmBoth) or (CheckMode=cmDoubleClick) then Toggle(ItemIndex);
  618. end;
  619.  
  620. procedure TCheckListBox.MouseDown(Button: TMouseButton; Shift: TShiftState;
  621.   X, Y: Integer);
  622. begin
  623.   inherited MouseDown(Button, Shift, X, Y);
  624.   ItemIndex := SetIndex(Row);
  625.   if (X<=ItemHeight) and ((CheckMode=cmBoth) or (CheckMode=cmCheckboxClick)) then Toggle(Row);
  626. end;
  627.  
  628. procedure TCheckListBox.DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);
  629. var
  630.    RectCheck      : TRect;
  631.    OldColor,
  632.    OldPenColor    : TColor;
  633.    pText          : PChar;
  634.  
  635.    procedure DrawCheckMark;
  636.    var
  637.       cOldColor : TColor;
  638.       iOldWidth,
  639.       Halfy, i,
  640.       x, y      : Integer;
  641.    begin
  642.      with Canvas do
  643.       begin
  644.         InflateRect(RectCheck, -3, -3);
  645.         cOldColor := Pen.Color;
  646.         iOldWidth := Pen.Width;
  647.         if (State[ARow]=csGrayed) and GrayCheckMark then
  648.          Pen.Color := clBtnShadow
  649.         else
  650.          Pen.Color := clBlack;
  651.         Pen.Width := 1;
  652.         with RectCheck do
  653.          begin
  654.            if NewStyle then
  655.             begin
  656.               { Draw the real 95 style checkmark }
  657.               halfy := top+(bottom-top) div 2 + 1;
  658.               for i:=0 to 2 do
  659.                begin
  660.                  PolyLine([Point(left,halfy-i), Point(left+2, halfy+2-i)]);
  661.                  PolyLine([Point(left+2, halfy+2-i), Point(left+7, halfy-3-i)]);
  662.                end;
  663.             end
  664.            else
  665.             begin
  666.               if CheckCtl3D then
  667.                begin
  668.                  { Draw a fat cross }
  669.                  PolyLine([Point(left,top), Point(right, bottom)]);
  670.                  PolyLine([Point(left+1,top), Point(right, bottom-1)]);
  671.                  PolyLine([Point(left,top+1), Point(right-1, bottom)]);
  672.                  PolyLine([Point(left,bottom-1), Point(right, top-1)]);
  673.                  PolyLine([Point(left,bottom-2), Point(right-1, top-1)]);
  674.                  PolyLine([Point(left+1,bottom-1), Point(right, top)]);
  675.                end
  676.               else
  677.                begin
  678.                  if State[ARow]=csGrayed then
  679.                   begin
  680.                     for x:=0 to right-left+1 do
  681.                      for y:=0 to bottom-top+1 do
  682.                       if ((x mod 2=0) and (y mod 2<>0)) or
  683.                          ((x mod 2<>0) and (y mod 2=0)) then
  684.                        Pixels[left-1+x,top-1+y] := clBlack;
  685.                   end
  686.                  else
  687.                   begin
  688.                     { Draw a thin cross }
  689.                     PolyLine([Point(left-1,top-1), Point(right+1, bottom+1)]);
  690.                     PolyLine([Point(left-1,bottom), Point(right+1, top-2)]);
  691.                   end;
  692.                end;
  693.             end;
  694.          end;
  695.       end;
  696.    end;
  697.  
  698. begin
  699.   CopyRect(RectCheck, ARect);
  700.   RectCheck.left := ((ARect.Bottom-ARect.Top) - (FMinWidth)) div 2;
  701.   RectCheck.top := ARect.top + ((ARect.Bottom-ARect.Top) - (FMinWidth)) div 2;
  702.   RectCheck.bottom := RectCheck.top + FMinWidth;
  703.   RectCheck.right := RectCheck.left + FMinWidth;
  704.   with Canvas do
  705.    begin
  706.      Font := Self.Font;
  707.      Brush.Color := Color;
  708.      if ItemIndex=ARow then
  709.       begin
  710.         Font.Color := clHighlightText;
  711.         Brush.Color := clHighlight;
  712.       end;
  713.      FillRect(ARect);
  714.      if Items.Count>0 then
  715.       begin
  716.         OldColor := Brush.Color;
  717.         OldPenColor := Pen.Color;
  718.         if CheckCtl3D then
  719.          begin
  720.            with RectCheck do
  721.             begin
  722.               Pen.Color := clBtnShadow;
  723.               PolyLine([Point(left, bottom-1), Point(left, top), Point(right, top)]);
  724.               Pen.Color := clBlack;
  725.               PolyLine([Point(left+1, bottom-2), Point(left+1, top+1), Point(right-1, top+1)]);
  726.               Pen.Color := clBtnFace;
  727.               PolyLine([Point(right-2, top+1), Point(right-2, bottom-2), Point(left, bottom-2)]);
  728.               Pen.Color := clBtnHighlight;
  729.               PolyLine([Point(left, bottom-1), Point(right-1, bottom-1), Point(right-1, top-1)]);
  730.             end;
  731.          end
  732.         else
  733.          begin
  734.            if NewStyle then Pen.Color := clBtnShadow;
  735.            Rectangle(RectCheck.left+1, RectCheck.top+1, RectCheck.right-1, RectCheck.bottom-1);
  736.          end;
  737.         if (State[ARow]=csGrayed) and (NewStyle or ((not NewStyle) and CheckCtl3D)) then
  738.          Brush.Color := clBtnFace
  739.         else
  740.          Brush.Color := clWindow;
  741.         InflateRect(RectCheck, -2, -2);
  742.         FillRect(RectCheck);
  743.         InflateRect(RectCheck, 2, 2);
  744.         if State[ARow]<>csUnchecked then DrawCheckMark;
  745.         Brush.Color := OldColor;
  746.         Pen.Color := OldPenColor;
  747.       end;
  748.      inc(ARect.left, ARect.bottom-ARect.top);
  749.      if Items.Count>0 then
  750.       begin
  751.         pText := StrAlloc(Length(Items[ARow])+1);
  752.         try
  753.           StrPCopy(pText, Items[ARow]);
  754.           if not Enabled then Font.Color := clBtnShadow;
  755.           DrawText(Handle, pText, Length(Items[ARow]), ARect, DT_SINGLELINE or DT_VCENTER or DT_LEFT);
  756.         finally
  757.           StrDispose(pText);
  758.         end;
  759.       end;
  760.      if Focused and ((ItemIndex=ARow) or ((ItemIndex=-1) and (Items.Count=0))) then
  761.       begin
  762.         dec(ARect.left, ARect.bottom-ARect.top);
  763.         FFocusRect := ARect;
  764.         if FShowFocusRect then DrawFocusRect(FFocusRect);
  765.       end;
  766.    end;
  767. end;
  768.  
  769. end.
  770.